/*
Copyright 2011, CSE Shareware Foundation
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, 
   this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, 
   this list of conditions and the following disclaimer in the documentation 
   and/or other materials provided with the distribution.
 * Neither the name of CSE Shareware Foundation nor the names of its contributors 
   may be used to endorse or promote products derived from this software without 
   specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef _MODULES_H_CSEAPI_
#define _MODULES_H_CSEAPI_

class CSE_IMPEXP_IN TCseRegister
{
private:
    // constructor is disabled
    TCseRegister() { }
    TCseRegister(const TCseRegister&);

    friend CSE_IMPEXP_IN void CseModules_init();

public:
    TBool exist(const TCharArray& key) const;
    TCseObj get(const TCharArray& key) const;
    const TCseObj& set(const TCharArray& key, const TCseObj& value) const;
    void remove(const TCharArray& key) const;

    TCseObj hold(const TCseObj& value) const;
};

extern CSE_IMPEXP_IN TCseRegister *CseRegister;

class CSE_IMPEXP_IN TCseModule: public TCseObj
{
public:
    TCseModule(const TCseObj& module);
    TCseModule(const TCharArray& sModule, TBool OnlyTopLevel=false);

    static TCharArray searchFile(const TCharArray& sModule, const TCharArray& RefFile=CseEmptyStr, TBool SysInc=false);
    static TCseObj getModule(const TCharArray& sModule, TBool OnlyTopLevel=false);
    static void setModule(const TCharArray& sModule, const TCseObj& mod);
    static void *CFuncAddr(const TCseObj& vFunc);

    static TCseModule create(const TCharArray& sModule, TBool regist=true);
    static TCseModule loadCsd(const TCharArray& sModule, const TCharArray& RefFile=CseEmptyStr);
    static void unloadAll(TBool safeExit=false);

    TBool useModule(const TCseModule& module) const;

    void clear() const;
    const TCseObj& attrSet(const TCharArray& attr, const TCseObj& value) const;
    TCseObj attrGet(const TCharArray& attr) const;

    void addSymList(const TCharArray& name, TInt iFlag, TBool ErrWhenDup=true) const;
    int addSymAddr(void *addr) const;
    int addExitFunc(void *func) const; // exit function should be "void (*)()"
    int addModuleVar(const TCseObj& var) const;
    TBool addSubModule(const TCharArray& name, const TCseObj& SubModule) const;
};

extern CSE_IMPEXP_IN TInt Cse_CallCdecl(void *pFunc, const TObjArray& bArgs);
extern CSE_IMPEXP_IN TInt Cse_CallStdcall(void *pFunc, const TObjArray& bArgs);
extern CSE_IMPEXP_IN TInt Cse_CallThiscall(void *pFunc, void *pSelf, const TObjArray& bArgs);

extern CSE_IMPEXP_IN void CseModules_init();
extern CSE_IMPEXP_IN void CseModules_SetArg(int argc, TXchar **argv);
extern CSE_IMPEXP_IN void CseModules_SetArgA(int argc, TChar **argv);
extern CSE_IMPEXP_IN void CseModules_SetArgW(int argc, TWchar **argv);
extern CSE_IMPEXP_IN void CseModules_exit();

extern CSE_IMPEXP_IN TCseObj Cse_EvalScript(const TXchar *script);
extern CSE_IMPEXP_IN TCharArray Cse_RawPrint(const TCharArray& s);
extern CSE_IMPEXP_IN TCharArray Cse_RawPrompt(const TCharArray& s);

extern "C" {
  #define MEMBER_OFF(UdtType,attr)      ((void*)&(((UdtType *)0L)->attr))
  #define MEMBER_OFF1(UdtType,attr)     ((TInt)&(((UdtType *)0L)->attr))
  #define MEMBER_OFF2(UdtType,m1,m2)    ((void*)((char*)&(((UdtType*)0L)->m2) - (char*)&(((UdtType*)0L)->m1)))
  #define ATTR_ADDR1(UdtType,attr)      ((TInt)Cse_FuncAddr(NULL,&UdtType::attr))
  #define METHOD_ADDR(UdtType,method)   Cse_FuncAddr(NULL,&UdtType::method)
  #define BASE_CLS_OFFSET(Cls,Bse,mth)  ((void*)((char*)&(((Cls*)0L)->mth) - (char*)&(((Bse*)0L)->mth)))
  #define FUNC_ADDR(addr)               Cse_FuncAddr(NULL,addr)
  #define FUNC_ADDR1(addr)              ((TInt)Cse_FuncAddr(NULL,addr))

  extern CSE_IMPEXP_IN void *Cse_FuncAddr(char *fmt,...);

  extern CSE_IMPEXP_IN const TXchar *Cse_GetHost();
  extern CSE_IMPEXP_IN void Cse_SetHost(const TXchar *name);

  extern CSE_IMPEXP_IN CseObj Cse_CreateModule(const TXchar *sModule);
  extern CSE_IMPEXP_IN void Cse_SetSymList(CseObj module, const TXchar *name, TInt iFlag);
  extern CSE_IMPEXP_IN int Cse_AddSymbol(CseObj module, void *addr);
  extern CSE_IMPEXP_IN int Cse_AddOnExit(CseObj module, void *func);
  extern CSE_IMPEXP_IN void Cse_SetArgument(int argc, TXchar **argv);
  extern CSE_IMPEXP_IN CseObj Cse_LoadCsd(const TCharArray& sModule, const TCharArray& RefFile);
}

#endif
